local jass = require 'jass.common'
local japi = require 'jass.japi'
local slk = require 'jass.slk'
local japi2 = require 'util.japi2'
local lflag = require 'util.flag'
local UnitAddAbility 	= jass.UnitAddAbility
local UnitRemoveAbility = jass.UnitRemoveAbility
local AbilityPermanent = jass.UnitMakeAbilityPermanent


local AF6X = FourCC('AF6X')
local function SetApivFadetime(fadetime)
	local unit = ac.dummy_unit
	jass.UnitAddAbility(unit.handle, AF6X)
	jass.SetUnitAbilityLevel(unit.handle, AF6X, 2)
	japi.EXSetAbilityDataReal(japi.EXGetUnitAbility(unit.handle , AF6X) , 1 , 102 , fadetime )
	japi.EXSetAbilityDataReal(japi.EXGetUnitAbility(unit.handle , AF6X) , 1 , 102 , fadetime )
	jass.SetUnitAbilityLevel(unit.handle, AF6X, 1)
	jass.UnitRemoveAbility(unit.handle, AF6X)
end 

--缴械
local function restriction_attack(unit, flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'Abun' )
		-- UnitAddAbility(unit.handle, FourCC 'Sbun' )
		AbilityPermanent(unit.handle, true, FourCC 'Abun')
		-- AbilityPermanent(unit.handle, true, FourCC 'Sbun')
	else
		UnitRemoveAbility(unit.handle, FourCC 'Abun' )
		-- UnitRemoveAbility(unit.handle, FourCC 'Sbun' )
	end
end

--晕眩
local function restriction_stun(unit,flag)
	if flag then
        japi.EXPauseUnit(unit.handle, true)
    else
        japi.EXPauseUnit(unit.handle, false)
	end
end

--无敌
local function restriction_god(unit,flag)
	if flag then
		unit:add_restriction "伪无敌"
    else
		unit:remove_restriction '伪无敌'
	end
end

--伪无敌
local function restriction_god2(unit,flag)
	if flag then
		unit:add_restriction '免伤'
		UnitAddAbility(unit.handle, FourCC 'Avul')
		AbilityPermanent(unit.handle, true, FourCC 'Avul')
    else
		unit:remove_restriction '免伤'
		UnitRemoveAbility(unit.handle, FourCC 'Avul')
	end
end

--幽灵
local function restriction_collision(unit,flag)
	-- if flag then
	-- 	UnitAddAbility(unit.handle, FourCC 'Aeth')
	-- 	AbilityPermanent(unit.handle, true, FourCC 'Aeth')
	-- else
	-- 	UnitRemoveAbility(unit.handle, FourCC 'Aeth')
	-- end
    
	if flag then
        japi.EXSetUnitMoveType(unit.handle, 16)
	else
        japi.EXSetUnitMoveType(unit.handle, 2)
	end
end

--蝗虫
local function restriction_aloc(unit,flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'Aloc')
		AbilityPermanent(unit.handle, true, FourCC 'Aloc')
	else
		UnitRemoveAbility(unit.handle, FourCC 'Aloc')
	end
end


--定身
local function restriction_ground(unit,flag)
	if flag then
		-- unit:set_propwindow(0)
		-- jass.UnitAddType(unit.handle, jass.UNIT_TYPE_ANCIENT) --解决装载问题
		japi2.SetUnitMovement(unit.handle, false)

	else
		japi2.SetUnitMovement(unit.handle, true)
		-- unit:set_propwindow( unit:get_default_propwindow() )
		-- jass.UnitRemoveType(unit.handle, jass.UNIT_TYPE_ANCIENT) --解决装载问题
	end
end

--扎根
local function restriction_root(unit,flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'AF6Z')
		AbilityPermanent(unit.handle, true, FourCC 'AF6Z')
        unit:remove_animation('alternate')
	else
		UnitRemoveAbility(unit.handle, FourCC 'AF6Z')
	end
end

local function restriction_silent(unit,flag)
	if flag == true then 
		for skl in unit:each_skill() do 
			if skl.id ~= 0 and skl.physics == false then 
				skl:set_silent(true)
			end 
		end 
	else 
		for skl in unit:each_skill() do 
			if skl.id ~= 0 and skl.physics == false then 
				skl:set_silent(false)
			end 
		end 
	end
end

local function restriction_unmana(unit, flag)
	if flag == true then 
		for skl in unit:each_skill() do 
			if skl.id ~= 0 then 
				skl:set_silent(true)
			end 
		end 
	else 
		for skl in unit:each_skill() do 
			if skl.id ~= 0 then 
				skl:set_silent(false)
			end 
		end 
	end
end 

local function restriction_moving(unit,flag)

end 

--免死
local function restriction_dead(unit,flag)

end

--免伤
local function restriction_damage(unit,flag)

end

--抗性
local function restriction_resistance(unit,flag)
	if flag then
		jass.UnitAddType(unit.handle, jass.UNIT_TYPE_ANCIENT)
	else
		jass.UnitRemoveType(unit.handle, jass.UNIT_TYPE_ANCIENT) 
	end
end 

-- 硬直
local function restriction_rigidity(unit,flag)
	if flag then
		unit:add_restriction "晕眩"
	else
		unit:remove_restriction "晕眩"
	end
end 

--免控
local function restriction_control(unit,flag)
	if flag then
		for buff in unit:each_buff() do 
			if buff:is_debuff() and buff:is_control() and (not buff:is_physics()) then 
				buff:remove()
			end
		end
	end
end

--免疫减速
local function restriction_unspeed(unit,flag)

end 

--失控
local function restriction_uncontrol(unit,flag)

end 

--夜视
local function restriction_nightvision(unit,flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'A004' )
		AbilityPermanent(unit.handle, true, FourCC 'A004')
	else
		UnitRemoveAbility(unit.handle, FourCC 'A004' )
	end
end 

--真视
local function restriction_realvision(unit,flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'A006' )
		AbilityPermanent(unit.handle, true, FourCC 'A006')
	else
		UnitRemoveAbility(unit.handle, FourCC 'A006' )
	end
end 


--禁锢
local function restriction_prison(unit,flag)
	-- 禁锢状态下 位移buff 和 击飞buff 无法生效
	if flag then 
		unit:add_restriction "定身"
	else
		unit:remove_restriction "定身"
	end 
end

-- 隐藏
local function restriction_hide(unit, flag)
	jass.ShowUnit(unit.handle, not flag)
end


--破隐
local function restriction_show(unit,flag)
	if flag then 
		-- 影遁给他干掉
		if unit:has_restriction "隐身" then 
			UnitRemoveAbility(unit.handle, AF6X)
		end 
	else
		if unit:has_restriction "隐身" then 
			SetApivFadetime(unit._restriction_apiv_fadetime or 0)
			UnitAddAbility(unit.handle, AF6X)
			AbilityPermanent(unit.handle, true, AF6X)
		end 
	end 
end

--隐身
local function restriction_stealth(unit, flag, fadetime)
	if flag then 
		unit._restriction_apiv_fadetime = fadetime
		if not unit:has_restriction '破隐' then 
			SetApivFadetime(fadetime or 0)
			UnitAddAbility(unit.handle, AF6X)
			AbilityPermanent(unit.handle, true, AF6X)
		end 
	else
		UnitRemoveAbility(unit.handle, AF6X)
		unit._restriction_apiv_fadetime = 0
	end
end 

--游荡
local function restriction_random(unit,flag)
	if flag then
		UnitAddAbility(unit.handle, FourCC 'Awan')
		AbilityPermanent(unit.handle, true, FourCC 'Awan')
	else
		UnitRemoveAbility(unit.handle, FourCC 'Awan')
	end
end

--控制
local function restriction_control(unit,flag)

end 

-- 相位
local function restriction_windwalk(unit, flag)
	if flag then
		japi.EXSetUnitMoveType(unit.handle, 0x10)
	else
		unit:set_move_type(unit:get_move_type())
	end
end 

-- 懒惰 
-- 建造 修理 采矿 都得 干掉
local function restriction_lazy(unit, flag)
	if flag == true then 
		japi.EXPauseUnit(unit.handle, true)
		japi2.SilentUnitAbility(unit.handle, FourCC("AHbu"), true)
		japi2.SilentUnitAbility(unit.handle, FourCC("A000"), true)
		japi2.SilentUnitAbility(unit.handle, FourCC("A00D"), true)
		japi.EXPauseUnit(unit.handle, false)
	else 
		japi2.SilentUnitAbility(unit.handle, FourCC("AHbu"), false)
		japi2.SilentUnitAbility(unit.handle, FourCC("A000"), false)
		japi2.SilentUnitAbility(unit.handle, FourCC("A00D"), false)
	end 
end 

-- 诱捕
local function restriction_ensnare(unit, flag )
	if flag == true then 
        unit:add_restriction '禁锢'
        unit:add_restriction '懒惰'
	else 
        unit:remove_restriction '禁锢'
        unit:remove_restriction '懒惰'
	end 
end 

-- 缠绕
local function restriction_entangling(unit, flag )
	if flag == true then 
        unit:add_restriction '沉默'
        unit:add_restriction '缴械'
        unit:add_restriction '禁锢'
        unit:add_restriction '懒惰'
	else 
        unit:remove_restriction '沉默'
        unit:remove_restriction '缴械'
        unit:remove_restriction '禁锢'
        unit:remove_restriction '懒惰'
	end 
end 

-- 禁疗
local function restriction_unheal(unit, flag )
	unit:refresh_regen()
end 

-- 闪避禁用
local function restriction_unmiss(unit, flag )

end 

-- 闭锁
local function restriction_itemlock(unit, flag )
	for item in unit:search_items() do 
		unit:notify((flag and ("单位-移除物品属性") or ("单位-添加物品属性")), unit, item)
	end
end 

-- 不可选取
local function restriction_unselector(unit, flag )
	if flag then 
		unit.default_as_targettype = japi2.GetUnitAsTargetType(unit.handle)
		japi2.SetUnitAsTargetType(unit.handle, 0)
		unit:remove_movers()
	else 
		japi2.SetUnitAsTargetType(unit.handle, unit.default_as_targettype)
	end 
end 

-- 禁止拾取物品
local function restriction_disable_pick_item()
end

-- 吟唱
local function restriction_sing(unit, flag)
	if flag then
		-- if unit._restriction_hard_flag then
		-- 	japi.EXPauseUnit(unit.handle, false)
		-- 	unit._restriction_hard_flag = false
		-- end
		unit:add_ability 'A40J'
		
		--local handle = japi.EXGetUnitAbility(unit.handle, base.string2id('A40J'))
		--japi.EXSetAbilityDataReal(handle, 1, 0x6E, 0x01)
		--unit:set_ability_level('A40J', 2)
		--unit:set_ability_level('A40J', 1)

		local res = jass.IssueImmediateOrder(unit.handle, 'thunderclap')
		unit:issue_order('thunderclap')
		if unit._last_cast_animation then
			unit._hard_2_cast_animation_timer = ac.wait(20, function (t)
				unit:set_animation(unit._last_cast_animation)
				if unit._last_cast_animation and unit._last_cast_animation_loop_times and unit._last_cast_animation_loop_times > 0 then
					for i = 1, unit._last_cast_animation_loop_times do
						unit:add_animation(unit._last_cast_animation)
					end
				end
			end)
		end
	else
		--在释放技能的过程中，删除技能并不会打断当前命令，单位会站在原地不动，需要再发布一次命令来打断这个技能，具体的看地图怎么设计
		unit:remove_ability 'A40J'
		if unit:has_restriction '硬直' then
			-- if not unit._restriction_hard_flag then
			-- 	japi.EXPauseUnit(unit.handle, true)
			-- 	unit._restriction_hard_flag = true
			-- end
		end

		if unit._hard_2_cast_animation_timer and not unit._hard_2_cast_animation_timer.removed then
			unit._hard_2_cast_animation_timer:remove()
		end
	end
end


local restriction_type = {
	['吟唱']		    = restriction_sing,
	['隐身']			= restriction_stealth,
	['破隐']			= restriction_show,
	['隐藏']			= restriction_hide,
	['缴械']			= restriction_attack,
	['晕眩']			= restriction_stun,
	['硬直']			= restriction_rigidity,
	['无敌']			= restriction_god,
	['幽灵']			= restriction_collision,
	['定身']			= restriction_ground,
	['禁锢']			= restriction_prison,
	['免死']			= restriction_dead,
	['蝗虫']			= restriction_aloc,
	['失控']			= restriction_uncontrol,
	['扎根']			= restriction_root,
	['免伤']			= restriction_damage,
	['抗性']			= restriction_resistance,
	['免控']			= restriction_control,
	['游荡']			= restriction_random,
	['沉默']			= restriction_silent,
	['位移']			= restriction_moving,
	['伪无敌']			= restriction_god2,
	['相位']			= restriction_windwalk,
	['诱捕']			= restriction_ensnare,
	['缠绕']			= restriction_entangling,
	['懒惰']			= restriction_lazy,
	['夜视']			= restriction_nightvision,
	['真视']			= restriction_realvision,
	['闭锁']			= restriction_itemlock,
	['禁疗']			= restriction_unheal,
	['禁魔']			= restriction_unmana,
	['不可选取'] 		= restriction_unselector,
	['减速免疫'] 		= restriction_unspeed,
	['闪避禁用'] 		= restriction_unmiss,
    ['禁止拾取物品']    = restriction_disable_pick_item,
}

ac.restriction = restriction_type

local mt = ac.unit.__index

--添加限制类型
function mt:add_restriction(name, ...)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return 0
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	res[name] = (res[name] or 0) + 1
	if res[name] == 1 and restriction_type[name] then
		restriction_type[name](self, true, ...)
		self:notify("单位-添加限制类型", self, name)
	end
	return res[name]
end

--删除限制类型
function mt:remove_restriction(name)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return 0
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	res[name] = (res[name] or 0) - 1
	if res[name] == 0 and restriction_type[name] then
		restriction_type[name](self, false)
		self:notify("单位-移除限制类型", self, name)
	end
	if res[name] == -1 then
		log.error('计数错误', name)
	end
	return res[name]
end

--获取限制类型层数
function mt:get_restriction(name)
	if not restriction_type[name] then
		log.error('错误的限制类型', name)
		return false
	end
	local res = self['限制']
	if not res then
		res = {}
		self['限制'] = res
	end
	return res[name] or 0
end

--拥有限制类型
function mt:has_restriction(name)
	return self:get_restriction(name) > 0
end

--刷新限制类型
function mt:ref_restriction(name)
	if self:has_restriction(name) then 
		restriction_type[name](self, false )
		restriction_type[name](self, true )
	end 
end

return restriction_type